#ifndef GLOBALPAGEMANAGER_H
#define GLOBALPAGEMANAGER_H

#include <QObject>
#include <QString>
#include <QMap>
#include <QPair>
#include <QMutex>
#include <memory>
#include <optional>
#include "pagenumber_v2_simplified.h"  // 新类型系统

/**
 * @brief 全局页码管理器 - Martin Fowler重构原则：Single Source of Truth
 *
 * 负责管理整个应用的页码连续性，包括：
 * - 全局页码状态维护
 * - 文件间页码映射计算
 * - 文件排序后的页码重计算
 * - 页码连续性保证
 *
 * 设计原则：
 * - Singleton Pattern：确保唯一实例
 * - Thread Safety：使用QMutex保护并发访问
 * - Observer Pattern：页码变更时通知所有观察者
 */
class GlobalPageManager : public QObject
{
    Q_OBJECT

public:
    /**
     * 获取单例实例
     * @return GlobalPageManager单例引用
     */
    static GlobalPageManager& instance();

    /**
     * 销毁单例实例
     */
    static void destroyInstance();

    /**
     * 获取全局页码管理器（为了兼容性）
     * @return GlobalPageManager单例引用
     */
    static GlobalPageManager* getInstance();

public:
    explicit GlobalPageManager(QObject* parent = nullptr);

    // === 全局页码状态管理 ===

    /**
     * @brief 获取当前全局页码
     * @return 当前全局页码（1-based）
     */
    int getCurrentGlobalPage() const { return m_currentGlobalPage; }

    /**
     * @brief 设置当前全局页码
     * @param globalPage 全局页码（1-based）
     */
    void setCurrentGlobalPage(int globalPage);

    /**
     * @brief 获取全局总页数
     * @return 全局总页数
     */
    int getTotalGlobalPages() const { return m_totalGlobalPages; }

    /**
     * @brief 获取已映射的文件数量
     * @return 文件数量
     */
    int getMappedFileCount() const { return m_fileDisplayPages.size(); }

    /**
     * @brief 设置全局总页数
     * @param totalPages 全局总页数
     */
    /**
     * @deprecated 不要使用此方法！会导致数据不一致
     * @brief 直接更新总页数（危险！不更新startPages映射）
     * 
     * 此方法会导致 m_totalGlobalPages 与 m_fileStartPages 不一致。
     * 请改用 recalculatePageMappings() 或让CustomFileBrowser重新计算。
     */
    [[deprecated("使用recalculatePageMappings()代替，避免数据不一致")]]
    void updateTotalPages(int totalPages);

    // === 文件页码映射计算（类型安全API） ===
    
    /**
     * @brief 获取文件的全局页码上下文
     * @param fileIdentity 文件唯一标识
     * @param fileArrayIndex 文件内数组索引（0-based）
     * @return 全局页码上下文，如果文件不存在返回nullopt
     */
    std::optional<PageNumberV2::GlobalPageContext> getPageContext(
        const QString& fileIdentity,
        PageNumberV2::ArrayIndex fileArrayIndex
    ) const;
    
    /**
     * @brief 获取文件的起始页码
     * @param fileIdentity 文件唯一标识
     * @return 起始页码，如果文件不存在返回nullopt
     */
    std::optional<PageNumberV2::PageNumber> getFileStartPageNumber(
        const QString& fileIdentity
    ) const;
    
    /**
     * @brief 获取文件的全局页码范围
     * @param fileIdentity 文件唯一标识
     * @return QPair<起始页码, 结束页码>（1-based，包含边界）
     */
    QPair<int, int> getFileGlobalRange(const QString& fileIdentity) const;

    // ========== 兼容旧代码的便捷方法 ==========
    
    /**
     * @brief 将文件内索引转换为全局页码（返回int）
     * @param fileIdentity 文件唯一标识
     * @param localPage 文件内数组索引（0-based）
     * @return 全局页码（1-based），如果失败返回0
     */
    int convertToGlobalPage(const QString& fileIdentity, int localPage) const;
    
    /**
     * @brief 将全局页码转换为文件内索引
     * @param fileIdentity 文件唯一标识
     * @param globalPage 全局页码（1-based）
     * @return 文件内数组索引（0-based），如果不在范围内返回-1
     */
    int convertToLocalPage(const QString& fileIdentity, int globalPage) const;
    
    /**
     * @brief 获取文件的全局起始页码（返回int）
     * @param fileIdentity 文件唯一标识
     * @return 起始页码（1-based），如果文件不存在返回0
     */
    int getFileStartPage(const QString& fileIdentity) const;

    /**
     * @brief 设置页码起始偏移量（影响所有文件的全局页码计算）
     * @param startOffset 起始偏移量（1-based，默认为1）
     */
    void setPageNumberStartOffset(int startOffset);

    /**
     * @brief 获取页码起始偏移量
     * @return 起始偏移量（1-based）
     */
    int getPageNumberStartOffset() const;

    // === 文件排序和状态更新 ===

    /**
     * @brief 更新文件信息（文件加载、排序后调用）
     * @param fileIdentity 文件唯一标识
     * @param displayPages 显示页数
     */
    void updateFileInfo(const QString& fileIdentity, int displayPages);

    /**
     * @brief 移除文件信息（文件删除时调用）
     * @param fileIdentity 文件唯一标识
     */
    void removeFileInfo(const QString& fileIdentity);

    /**
     * @brief 文件排序后重新计算页码映射
     */
    void recalculatePageMappings();

    /**
     * @brief 清空所有文件信息（新会话开始时调用）
     */
    void clearAllFileInfo();

    // === 调试和状态查询 ===

    /**
     * @brief 获取调试信息
     * @return 调试信息字符串
     */
    QString getDebugInfo() const;

    /**
     * @brief 验证页码映射一致性
     * @return 验证结果和错误信息
     */
    QPair<bool, QString> validatePageMappings() const;

signals:
    /**
     * @brief 全局页码发生变化
     * @param globalPage 新的全局页码
     */
    void globalPageChanged(int globalPage);

    /**
     * @brief 全局总页数发生变化
     * @param totalPages 新的全局总页数
     */
    void totalGlobalPagesChanged(int totalPages);

    /**
     * @brief 页码映射发生变化（文件排序、添加、删除后）
     */
    void pageMappingsChanged();

    /**
     * @brief 文件页码范围发生变化
     * @param fileIdentity 文件唯一标识
     * @param startPage 起始页码
     * @param endPage 结束页码
     */
    void fileRangeChanged(const QString& fileIdentity, int startPage, int endPage);

    /**
     * @brief 页码起始偏移量发生变化
     * @param startOffset 新的起始偏移量
     */
    void pageNumberStartOffsetChanged(int startOffset);

private slots:
    /**
     * @brief 处理文件列表变化
     */
    void onFileListChanged();

private:
    /**
     * @brief 重新计算所有文件的页码映射
     */
    void recalculateMappings();

    /**
     * @brief 更新全局总页数
     */
    void updateTotalGlobalPages();

    /**
     * @brief 验证全局页码有效性
     * @param globalPage 要验证的页码
     * @return 是否有效
     */
    bool isValidGlobalPage(int globalPage) const;

private:
    static std::unique_ptr<GlobalPageManager> m_instance;
    static QMutex m_mutex;

    int m_currentGlobalPage = 0;  // 当前全局页码（1-based）
    int m_totalGlobalPages = 0;   // 全局总页数
    int m_pageNumberStartOffset = 1;  // 页码起始偏移量（1-based，默认为1）

    // 文件信息映射：文件标识 -> 显示页数
    QMap<QString, int> m_fileDisplayPages;

    // 文件起始页码映射：文件标识 -> 全局起始页码（类型安全）
    QMap<QString, PageNumberV2::PageNumber> m_fileStartPages;

    // 文件排序后的标识列表（维护文件顺序）
    QList<QString> m_orderedFileIdentities;
};

#endif // GLOBALPAGEMANAGER_H